﻿// //  ********************************************************************************
// //  Copyright (C) 2016 Sebastian Kenter. All rights reserved.
// // 
// //  Name    : PhotonServerProject | MasterServer | RealmListRequestHandler.cs
// //  Created : 2016 - 04 - 12 12:19
// //  Modified: 2016 - 04 - 18 09:38
// //  ********************************************************************************

using System;
using System.Collections.Generic;
using ExitGames.Logging;
using NHibernate;
using Photon.SocketServer;
using PhotonServerCommon;
using PhotonServerCommon.Entities.Domain;
using PhotonServerCommon.Enums;
using PhotonServerCommon.Messages;
using PhotonServerCommon.Messages.Helper;
using PhotonServerFramework.Implementation.Client;
using PhotonServerFramework.Implementation.Database;
using PhotonServerFramework.Implementation.Handler;
using PhotonServerFramework.Interfaces.Client;
using PhotonServerFramework.Interfaces.Telegram;

namespace MasterServer.Handler.Request
{
    public class RealmListRequestHandler : ClientTelegramHandler
    {
        /// <summary>
        ///     Logger instance
        /// </summary>
        public override ILogger Logger { get; }

        /// <summary>
        ///     Unique handler id
        /// </summary>
        public override Guid HandlerId { get; set; } = Guid.NewGuid();

        /// <summary>
        ///     Handler type (Request, Response or Event)
        /// </summary>
        public override HandlerTypes HandlerType => HandlerTypes.Request;

        /// <summary>
        ///     OperationCode that the handler can handle
        /// </summary>
        public override byte HandlerCode => (byte) OperationCodes.Transfer;

        /// <summary>
        ///     OperationSubCode that the handler can handle
        /// </summary>
        public override int HandlerSubCode => (int) OperationSubCodes.RequestRealmList;

        public RealmListRequestHandler(ILogger logger)
        {
            Logger = logger;
        }

        /// <summary>
        ///     Tries to handle the incoming telegram from the given TPeer (normally IClientPeer)
        /// </summary>
        /// <param name="telegram">The telegram to be handled</param>
        /// <param name="clientPeer">The peer requesting the handling</param>
        /// <returns>
        ///     true if handled, otherwise false
        /// </returns>
        public override bool HandleTelegram(ITelegram telegram, IClientPeer clientPeer)
        {
            bool handled = false;

            Logger.InfoFormat("Trying to handle telegram of type={0} with code={1}, subcode={2}", telegram.Type,
                (OperationCodes)telegram.TelegramCode, (OperationSubCodes)telegram.TelegramSubCode);

            ClientPeer peer = clientPeer as ClientPeer;

            IList<RealmT> realms = null;

            if (peer != null)
            {
                using (ISession session = SessionManager.OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        try
                        {
                            realms = session.QueryOver<RealmT>()
                                .Where(
                                    r =>
                                        r.Region ==
                                        telegram.TelegramParameters[(byte) ParameterCodes.RealmRegion].ToString())
                                .List<RealmT>();
                            transaction.Commit();
                        }
                        catch (Exception ex)
                        {
                            Logger.ErrorFormat("Operation failed with: {0}", ex.Message);
                            transaction.Rollback();
                        }
                    }

                    session.Close();
                }

                if (realms != null && realms.Count != 0)
                {
                    Logger.InfoFormat("Found {0} realms for region {1}", realms.Count,
                        telegram.TelegramParameters[(byte) ParameterCodes.RealmRegion]);

                    RealmList realmList = new RealmList();

                    foreach (RealmT realm in realms)
                    {
                        realmList.RealmServer.Add(new RealmServer
                                                  {
                                                      RealmName = realm.RealmName,
                                                      RealmServerId = realm.RealmServerId,
                                                      CurrentPopulation = realm.CurrentPopulation,
                                                      MaximumPopulation = realm.MaximumPopulation,
                                                      Queue = realm.Queue
                                                  });
                    }

                    telegram.TelegramParameters.Add((byte) ParameterCodes.RealmList,
                        MessageSerializer.SerializeMessage(realmList));

                    peer.SendOperationResponse(
                        new OperationResponse(telegram.TelegramCode, telegram.TelegramParameters)
                        {
                            ReturnCode =
                                (short)
                                ErrorCodes.Ok,
                            DebugMessage =
                                EnumHelper
                                .GetEnumDescription
                                (ErrorCodes.Ok)
                        },
                        new SendParameters());
                }

                handled = true;
            }

            return handled;
        }
    }
}
